package org.afk.tools.io;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.security.*;

import org.afk.tools.log.*;

public class PathHasher
{

	private static final String SHA_1 = "SHA-1";

	private final ErrorHandler errorHandler;

	private final String algorythm;

	private boolean disabled;

	public PathHasher(final ErrorHandler errorHandler, final String algorythm)
	{
		super();
		this.errorHandler = errorHandler;
		this.algorythm = algorythm != null ? algorythm : "off";
		if (this.algorythm.equals("off"))
			this.disabled = true;
	}

	private String printable(final byte[] digest)
	{
		final StringBuilder builder = new StringBuilder();
		for (final byte b : digest)
		{
			final String hexString = Integer.toHexString(b & 0xff);
			if (hexString.length() == 1)
				builder.append('0').append(hexString);
			else
				builder.append(hexString);
		}
		return builder.toString();
	}

	public String getAlgorythm()
	{
		return this.algorythm;
	}

	public String hash(final Path file) throws IOException
	{
		if (disabled)
			return null;

		final String algorythm1 = getAlgorythm();

		try (SeekableByteChannel in = Files.newByteChannel(file, StandardOpenOption.READ);)
		{
			final MessageDigest digest = MessageDigest.getInstance(algorythm1);
			final ByteBuffer buffer = ByteBuffer.allocateDirect(16000);
			for (;;)
			{
				final int read = in.read(buffer);
				if (read == -1)
					break;
				buffer.flip();
				digest.update(buffer);
				buffer.clear();
			}
			return printable(digest.digest());
		}
		catch (final NoSuchAlgorithmException e)
		{
			this.errorHandler.warning("Algorythm not supported: " + algorythm1);
		}
		return null;
	}

}
